﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace 基于灰度的裂纹长度测量系统
{
    public partial class Form1 : Form
    {
        //halcon类对象
        CrackDetect crackDetect = new CrackDetect();
        //指示是否镜像裂纹
        bool crackDirection = true;
        //图像最近一次历史路径
        string imagePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);

        /// <summary>
        /// 初始化窗体
        /// </summary>
        public Form1()
        {
            InitializeComponent();
            rb_left.Checked = true;
            rb_create.Checked = true;
            chk_continue.Checked = false;
            cb_thread_mid.DropDownStyle = ComboBoxStyle.DropDownList;
            cb_thread_mid.SelectedItem = cb_thread_mid.Items[3];
            cb_number.DropDownStyle = ComboBoxStyle.DropDownList;
            cb_number.SelectedItem = cb_number.Items[4];
            cb_thread.DropDownStyle = ComboBoxStyle.DropDownList;
            cb_thread.SelectedItem = cb_thread.Items[3];
            cb_window_size.DropDownStyle = ComboBoxStyle.DropDownList;
            cb_window_size.SelectedItem = cb_window_size.Items[1];
            rb_auto.Checked = true;
            cb_search_size.DropDownStyle = ComboBoxStyle.DropDownList;
            cb_search_size.SelectedItem = cb_search_size.Items[1];
            rb_median.Checked = true;
            rb_muti.Checked = true;
            tb_length.ReadOnly = true;
            cb_Energy.SelectedItem = cb_Energy.Items[1];
            cb_Distance.SelectedItem = cb_Distance.Items[2];
            cb_Difference.SelectedItem = cb_Difference.Items[4];
            //订阅刷新镜像裂纹参数事件
            crackDetect.change += new CrackDetect.ChangeDirection(changeDirectin_fresh);
        }

        void changeDirectin_fresh(bool fresh)
        {
            crackDirection = fresh;
        }

        /// <summary>
        /// 载入裂纹图像
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_LoadImage_Click(object sender, EventArgs e)
        {
            string path = getImagePath();
            if (path != null)
            {
                crackDetect.ReadImage(path, pictureBox1);
            }
            else
            {
                MessageBox.Show("缺少图像路径");
                return;
            }
        }

        /// <summary>
        /// 裂纹检测
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_detect_Click(object sender, EventArgs e)
        {
            //检查输入图像和空间分辨率
            if (!checkInput())
            {
                return;
            }
            //是否镜像判断
            if (rb_right.Checked == true && crackDirection == true)
            {
                crackDetect.MirroredImage(pictureBox1);
                //镜像判断后，指示改为false
                crackDirection = false;
            }
            //清空裂纹图像重新显示，防止上次检测痕迹残留
            crackDetect.clearPicturebox();
            //创建模板
            if (!createModel())
            {
                return;
            }
            //模板匹配
            crackDetect.ModelMatch();
            //起点检测失败则停止
            if (!crackDetect.startDetect())
            {
                return;
            }
            //滤波和叠加判断
            int filter = rb_median.Checked == true ? 0 : 1;
            int superpose = rb_muti.Checked == true ? 0 : 1;
            //裂纹区域选择
            if (rb_hand.Checked == true)
            {
                //聚焦
                this.Focus();
                //限制鼠标
                int a = (this.Width - this.ClientSize.Width) / 2;
                int b = this.Height - this.ClientSize.Height - a;
                Cursor.Clip = new Rectangle(pictureBox1.Location.X + this.Location.X + a,
                    pictureBox1.Location.Y + this.Location.Y + b,
                    pictureBox1.Width, pictureBox1.Height);
                //手动选裂纹区域
                crackDetect.drawCrackRegion();
                //解除限制
                Cursor.Clip = new Rectangle(Screen.PrimaryScreen.Bounds.Location,
                Screen.PrimaryScreen.Bounds.Size);
            }
            else
            {
                crackDetect.autoCrackRegion(int.Parse(cb_search_size.Text), superpose, float.Parse(cb_Energy.Text), float.Parse(cb_Distance.Text), float.Parse(cb_Difference.Text));
            }
            //裂纹检测
            crackDetect.crackDTSkeleton(filter, superpose, float.Parse(cb_Energy.Text), float.Parse(cb_Distance.Text), float.Parse(cb_Difference.Text));
            //裂纹及终点显示
            double length = crackDetect.crack_EndShow();
            //显示长度
            tb_length.Text = (length * double.Parse(tb_resolution.Text)).ToString();
        }

        /// <summary>
        /// 检查输入图像和空间分辨率
        /// </summary>
        /// <returns></returns>
        private bool checkInput()
        {
            if (!crackDetect.check_CrackImage())
            {
                MessageBox.Show("缺少裂纹图像");
                return false;
            }
            //利用正则表达式判断格式是否正确
            Regex reg = new Regex(@"^[0-9]+[.]??[0-9]*$");
            if (tb_resolution.Text == null || !reg.IsMatch(tb_resolution.Text))
            {
                MessageBox.Show("请输入正确的空间分辨率");
                return false;
            }  
            return true;
        }



        /// <summary>
        /// 获取图像路径
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private string getImagePath()
        {
            //打开文件对话框
            OpenFileDialog dialog = new OpenFileDialog();
            //打开后初始地址
            dialog.InitialDirectory = imagePath;
            //该值确定是否可以选择多个文件
            dialog.Multiselect = false;
            //对话框标题
            dialog.Title = "请选择模板图像";
            dialog.Filter = "所有图片文件(*.jpg,*.bmp,*.png,*.tif,*.tiff)|*.jpg;*.bmp;*.png;*.tif;*.tiff";
            if (dialog.ShowDialog() == DialogResult.OK)
            {
                //文件路径
                imagePath = dialog.FileName;
                //路径格式转换为halcon格式
                string path2 = imagePath.Replace("\\", "/");
                return path2;
            }
            return null;
        }

        /// <summary>
        /// 创建模板
        /// </summary>
        /// <returns></returns>
        private bool createModel()
        {
            //判断模板方式
            if (crackDetect.check_ModelImage() == true && chk_continue.Checked == true)
            {
                //已存在模板，不执行创建模板任务
            }
            else
            {
                //手动创建或读取
                if (rb_create.Checked == true)
                {
                    //聚焦
                    this.Focus();
                    //限制鼠标
                    int a = (this.Width - this.ClientSize.Width) / 2;
                    int b = this.Height - this.ClientSize.Height - a;
                    Cursor.Clip = new Rectangle(pictureBox1.Location.X + this.Location.X + a, 
                        pictureBox1.Location.Y + this.Location.Y + b, 
                        pictureBox1.Width, pictureBox1.Height);
                    //手动建模版
                    crackDetect.CreateModel(true, pictureBox2, "");
                    //解除限制
                    Cursor.Clip = new Rectangle(Screen.PrimaryScreen.Bounds.Location,
                    Screen.PrimaryScreen.Bounds.Size);
                }
                else
                {
                    string path = getImagePath();
                    if (path != null)
                    {
                        crackDetect.CreateModel(false, pictureBox2, path);
                    }
                    else
                    {
                        MessageBox.Show("缺少图像路径");
                        return false;
                    }
                }
            }
            return true;
        }
    }
}
